// 泛型 在声明函数 类 接口 的时候 先不指定具体的类型 而是在使用的时候 在指定类型的一种特性
// java  C#  

// function createArray(length:number,value:any):Array<any>{
//   let result = []
//   for (let i = 0;i<length;i++) {
//     result[i] = value
//   }
//   return result
// }
// createArray(3,'x') //?

//T U K 
function createArray<T>(length:number,value:T):Array<T>{
  let result = []
  for (let i = 0;i<length;i++) {
    result[i] = value
  }
  return result
}
createArray(3,'x') //?

// 声明一个泛型函数 使传递过来的元组 两个值发生位置变换 ['1',100]  [100,'1']

// 多类型参数

function swap<T , U>(tuple:[T , U]):[U , T]{
  return [tuple[1],tuple[0]]
}

swap([1,'234'])//?

// 泛型约束
// 在函数内部使用泛型变量的时候 由于实现不知道踏实哪种流行 , 所以不能随意操作它的属性或者方法
// function loggingIdentity<T>(arg:T){
//   console.log(arg.length)
//   return arg
// }

interface LengthWise{
  length:number
}

function loggingIdentity<T extends LengthWise>(arg:T){
    console.log(arg.length)
    return arg
}
// 泛型约束
// extends 扩展 
loggingIdentity({length:10})//?

// 声明一个函数(两个参数 T,U) T 和 U 要求 T继承U 返回值是T类型  
// 返回的数据 是将U上面的属性 赋值给T 

  function copyField <T extends U ,U> (target: T ,source :U): T{
    for( let key in source){
      target[key] = (<T>source)[key]
    }
    return target
  }

  let x = {a:1,b:2,c:3,d:4}
  // T包含U
  copyField(x,{c:12})//?


  // 作业 : 课堂的代码 每一个都认真捉摸一遍 
  // 2. 
  type User = {
    id:number;
    kind:string;
  }

  function makeCustomer<T extends User>(u:T):T{
    return {
      id:u.id,
      kind:'customer'
    }
  }
  // 为什么会出错 怎么改
  // 3 项目今晚之前必须提交完